/**
 * Created by Administrator on 2017/5/8.
 */

function Rect(x, y, size, context) {
    this.x = x;
    this.y = y;
    this.size = size;

    this.issetcolor = false;
    this.color = "";
    this.context = context;
}
Rect.prototype.strokerect = function (sColor) {

    this.context.strokeStyle = sColor;
    this.context.strokeRect(this.x * this.size + 0, this.y * this.size + 0, this.size, this.size);
}
Rect.prototype.fillrect = function (sColor) {
    this.context.fillStyle = sColor;
    this.context.fillRect(this.x * this.size + 1, this.y * this.size + 1, this.size - 2, this.size - 2);
    this.color = sColor;
}
//        Rect.prototype.clearrect = function () {
//            this.context.clearRect(this.x * this.size + 1,this.y * this.size + 1,this.size - 2,this.size - 2);
//        }
function map(RectSize, color, canvas) {
    this.width = canvas.width;
    this.height = canvas.height;
    this.RectSize = RectSize;
    this.backgroundcolor = color;
    this.aMapArray = null;
    this.ctx = canvas.getContext("2d");
    this.born();
}
map.prototype.born = function () {
    var i;
    var j;
    var xCount;
    var yCount;
    xCount = this.width / this.RectSize;
    yCount = this.height / this.RectSize;
    this.aMapArray = new Array();
    for (i = 0; i < xCount; i++) {
        this.aMapArray[i] = new Array();

        for (j = 0; j < yCount; j++) {
            this.aMapArray[i][j] = new Rect(i, j, this.RectSize, this.ctx);
            this.aMapArray[i][j].strokerect(this.backgroundcolor);
            this.aMapArray[i][j].fillrect(this.backgroundcolor);
        }
    }
}
map.prototype.refresh = function () {
    var xCount;
    var yCount;
    xCount = this.width / this.RectSize;
    yCount = this.height / this.RectSize;
    for (var i = 0; i < xCount; i++) {
        for (var j = 0; j < yCount; j++) {
            this.aMapArray[i][j].fillrect("White");
            this.aMapArray[i][j].fillrect(this.backgroundcolor);
            this.aMapArray[i][j].issetcolor = false;
        }
    }
}
map.prototype.getrect = function (x, y) {
    try {
        return this.aMapArray[x][y];
    }
    catch (err) {
        return null;
    }
}
function tetris(x, y, size, scolor) {

    this.born_x = x;
    this.born_y = y;
    this.rectsize = size;
    this.rectarray = new Array();
    this.color = scolor;
    this.name = "";
    this.map = map;
}
tetris.prototype.setbornxy = function (x, y) {
    this.born_x = x;
    this.born_y = y;
}
tetris.prototype.show = function () {
    var iCount = this.rectarray.length;
    for (var i = 0; i < iCount; i++) {
        this.rectarray[i].fillrect(this.color);
    }
}
tetris.prototype.clear = function () {
    var iCount = this.rectarray.length;
    for (var i = 0; i < iCount; i++) {
        this.rectarray[i].fillrect("#111");
    }
}
//随机彩色
var bgcolor = document.getElementById("canvas");

setInterval(function () {
    bgcolor.style.background = 'rgb(' + Math.floor(Math.random() * 255) + ',' + Math.floor(Math.random() * 255) + ',' + Math.floor(Math.random() * 255) + ')';
},500)


tetris.prototype.rand = function (num) {
    return Math.floor(Math.random() * num)

}
//旋转
tetris.prototype.trun = function () {
    var iCount = this.rectarray.length;
    var iTemp_x, iTemp_y, offset_x, offset_y;
    if (this.name != "田") {
        this.clear();

        offset_x = this.rectarray[0].x - 1;
        offset_y = this.rectarray[0].y - 1;
        for (var i = 1; i < iCount; i++) {

            iTemp_x = this.rectarray[i].x - offset_x;
            iTemp_y = this.rectarray[i].y - offset_y;

            this.rectarray[i].x = iTemp_y + offset_x;
            this.rectarray[i].y = 2 - iTemp_x + offset_y;
        }
        this.show();
    }
}

tetris.prototype.move_left = function () {

    var iCount = this.rectarray.length;
    this.clear();
    for (var i = 0; i < iCount; i++) {
        this.rectarray[i].x = this.rectarray[i].x - 1;
    }
    this.show();
}
tetris.prototype.move_right = function (context) {


    var iCount = this.rectarray.length;
    this.clear();
    for (var i = 0; i < iCount; i++) {
        this.rectarray[i].x = this.rectarray[i].x + 1;
    }
    this.show();
}

tetris.prototype.move_down = function (context) {

    var iCount = this.rectarray.length;
    this.clear();
    for (var i = 0; i < iCount; i++) {
        this.rectarray[i].y = this.rectarray[i].y + 1;
    }
    this.show();
};


function tetris_T(x, y, size, scolor) {
    tetris.call(this, x, y, size, scolor); //继承
}
tetris_T.prototype = new tetris();
tetris_T.prototype.born = function (context) {
    this.rectarray[0] = new Rect(this.born_x, this.born_y, this.rectsize, context);
    this.rectarray[1] = new Rect(this.born_x + 1, this.born_y, this.rectsize, context);
    this.rectarray[2] = new Rect(this.born_x, this.born_y - 1, this.rectsize, context);
    this.rectarray[3] = new Rect(this.born_x - 1, this.born_y, this.rectsize, context);
    this.name = "T";
}

function tetris_1(x, y, size, scolor, map) {
    tetris.call(this, x, y, size, scolor, map);
}
tetris_1.prototype = new tetris();
tetris_1.prototype.born = function (context) {
    this.rectarray[0] = new Rect(this.born_x, this.born_y, this.rectsize, context);
    this.rectarray[1] = new Rect(this.born_x - 1, this.born_y, this.rectsize, context);
    this.rectarray[2] = new Rect(this.born_x + 1, this.born_y, this.rectsize, context);
    this.rectarray[3] = new Rect(this.born_x + 2, this.born_y, this.rectsize, context);
    this.name = "1";
}

function tetris_D(x, y, size, scolor, map) {
    tetris.call(this, x, y, size, scolor, map);
}
tetris_D.prototype = new tetris();
tetris_D.prototype.born = function (context) {
    this.rectarray[0] = new Rect(this.born_x, this.born_y, this.rectsize, context);
    this.rectarray[1] = new Rect(this.born_x + 1, this.born_y, this.rectsize, context);
    this.rectarray[2] = new Rect(this.born_x + 1, this.born_y - 1, this.rectsize, context);
    this.rectarray[3] = new Rect(this.born_x, this.born_y - 1, this.rectsize, context);
    this.name = "田";
}
function tetris_LL(x, y, size, scolor, map) {
    tetris.call(this, x, y, size, scolor, map);
}
tetris_LL.prototype = new tetris();
tetris_LL.prototype.born = function (context) {
    this.rectarray[0] = new Rect(this.born_x, this.born_y, this.rectsize, context);
    this.rectarray[1] = new Rect(this.born_x + 1, this.born_y, this.rectsize, context);
    this.rectarray[2] = new Rect(this.born_x - 1, this.born_y - 1, this.rectsize, context);
    this.rectarray[3] = new Rect(this.born_x - 1, this.born_y, this.rectsize, context);
    this.name = "LL";
}
function tetris_RL(x, y, size, scolor, map) {
    tetris.call(this, x, y, size, scolor, map);
}
tetris_RL.prototype = new tetris();
tetris_RL.prototype.born = function (context) {
    this.rectarray[0] = new Rect(this.born_x, this.born_y, this.rectsize, context);
    this.rectarray[1] = new Rect(this.born_x + 1, this.born_y, this.rectsize, context);
    this.rectarray[2] = new Rect(this.born_x + 1, this.born_y - 1, this.rectsize, context);
    this.rectarray[3] = new Rect(this.born_x - 1, this.born_y, this.rectsize, context);
    this.name = "RL";
}
function tetris_RZ(x, y, size, scolor, map) {
    tetris.call(this, x, y, size, scolor, map);
}
tetris_RZ.prototype = new tetris();
tetris_RZ.prototype.born = function (context) {
    this.rectarray[0] = new Rect(this.born_x, this.born_y, this.rectsize, context);
    this.rectarray[1] = new Rect(this.born_x + 1, this.born_y - 1, this.rectsize, context);
    this.rectarray[2] = new Rect(this.born_x, this.born_y - 1, this.rectsize, context);
    this.rectarray[3] = new Rect(this.born_x - 1, this.born_y, this.rectsize, context);
    this.name = "RZ";
}
function tetris_Z(x, y, size, scolor, map) {
    tetris.call(this, x, y, size, scolor, map);
}
tetris_Z.prototype = new tetris();
tetris_Z.prototype.born = function (context) {
    this.rectarray[0] = new Rect(this.born_x, this.born_y, this.rectsize, context);
    this.rectarray[1] = new Rect(this.born_x + 1, this.born_y, this.rectsize, context);
    this.rectarray[2] = new Rect(this.born_x, this.born_y - 1, this.rectsize, context);
    this.rectarray[3] = new Rect(this.born_x - 1, this.born_y - 1, this.rectsize, context);
    this.name = "Z";
}
function rectfactory(rectsize) {
    this.rectsize = rectsize;
    this.colorarray = new Array("red", "green", "blue", "orange", "purple", "pink", "yellow");
}
//产生方块
rectfactory.prototype.createfactory = function (x, y, witch, icolor) {
    var tetris;
    switch (witch) {
        case 0:
            tetris = new tetris_T(x, y, this.rectsize, this.colorarray[icolor]);
            break;
        case 1:
            tetris = new tetris_1(x, y, this.rectsize, this.colorarray[icolor]);
            break;
        case 2:
            tetris = new tetris_D(x, y, this.rectsize, this.colorarray[icolor]);
            break;
        case 3:
            tetris = new tetris_LL(x, y, this.rectsize, this.colorarray[icolor]);
            break;
        case 4:
            tetris = new tetris_RL(x, y, this.rectsize, this.colorarray[icolor]);
            break;
        case 5:
            tetris = new tetris_RZ(x, y, this.rectsize, this.colorarray[icolor]);
            break;
        case 6:
            tetris = new tetris_Z(x, y, this.rectsize, this.colorarray[icolor]);
            break;
        default:
            tetris = null;
    }
    return tetris;
}
function tetrisgame(canvas, canvas2) {
    this.rectsize = 20;
    this.map = new map(this.rectsize, "#111", canvas);
    //预览地图
    this.map2 = new map(this.rectsize, "#111", canvas2);
    this.tetrisfactory = new rectfactory(this.rectsize);
    this.tetris = null;
    this.tetris2 = null;
    this.rectcreate_x = parseInt(this.map.aMapArray.length / 2);
    this.score = 0;
    this.scorebord = document.getElementById("score");
    this.level = 0;
    this.isstart = false;
};
//方块不能再向下移动时调用        再   判断是否Game Over
tetrisgame.prototype.isgameover = function (tetris) {
    var iCount = tetris.rectarray.length;
    var bHas = false;
    for (var i = 0; i < iCount; i++) {
        if (tetris.rectarray[i].y < 0) {
            bHas = true;
            break;
        }
    }
    return bHas;
}
//初始化
tetrisgame.prototype.gameover = function () {
    this.stop();
    this.tetris = null;
    this.tetris2 = null;
    this.score = 0;
    alert("game over 请重新开始");
    this.map.refresh();
    this.map2.refresh();
};
//产生
console.log(tetrisgame.prototype)
tetrisgame.prototype.createrect = function () {
    var icolor, ikind;
    icolor = parseInt(Math.random() * (this.tetrisfactory.colorarray.length - 1));
    ikind = parseInt(Math.random() * 6);
    //return this.tetrisfactory.createfactory(this.rectcreate_x,-1,ikind,icolor);
    return this.tetrisfactory.createfactory(2, 2, ikind, icolor);
}
tetrisgame.prototype.iscanmove_down = function (tetris, map) {
    var iCount = tetris.rectarray.length;
    var bord_y = map.aMapArray[0].length;

    var result = true;
    var x, y, maprect;
    for (var i = 0; i < iCount; i++) {
        x = tetris.rectarray[i].x;
        y = tetris.rectarray[i].y + 1;
        maprect = map.getrect(x, y);
        if (maprect == null && y < 0) {
            continue;
        }
        else if (maprect == null && y >= bord_y) {//刚产生方块时，不能移动
            result = false;
            break;
        }
        else if (maprect.issetcolor || y >= bord_y) {//着色不能移
            result = false;
            break;
        }
    }
    return result;
}
//左移  右移
tetrisgame.prototype.iscanmove_left = function (tetris, map) {
    var iCount = tetris.rectarray.length;

    var result = true;
    var x, y, maprect;
    for (var i = 0; i < iCount; i++) {
        x = tetris.rectarray[i].x - 1;
        y = tetris.rectarray[i].y;
        maprect = map.getrect(x, y);
        if (maprect == null && x >= 0) {
            continue;
        }
        else if (x < 0 || maprect.issetcolor) {
            result = false;
            break;
        }
    }
    return result;
};
tetrisgame.prototype.iscanmove_right = function (tetris, map) {
    var iCount = tetris.rectarray.length;
    var bord_x = map.aMapArray.length;

    var bord_y = map.aMapArray[0].length;
    console.log(bord_x);
    console.log(bord_y);
    var result = true;
    var x, y, maprect;
    for (var i = 0; i < iCount; i++) {
        x = tetris.rectarray[i].x + 1;
        y = tetris.rectarray[i].y;
        maprect = map.getrect(x, y);
        if (maprect == null && x < bord_x) {
            continue;
        }
        else if (x >= bord_x || maprect.issetcolor) {
            result = false;
            break;
        }
    }
    return result;
}
//判断是否能够旋转
tetrisgame.prototype.iscanturn = function (tetris, map) {
    var iCount = tetris.rectarray.length;
    var bord_x = map.aMapArray.length;
    var bord_y = map.aMapArray[0].length;
    var x, y, iTemp_x, iTemp_y, offset_x, offset_y;
    var result = true;
    var rect = null;
    if (tetris.name != "D") {
        offset_x = tetris.rectarray[0].x - 1;
        offset_y = tetris.rectarray[0].y - 1;
        for (var i = 1; i < iCount; i++) {
            iTemp_x = tetris.rectarray[i].x - offset_x;
            iTemp_y = tetris.rectarray[i].y - offset_y;
            x = iTemp_y + offset_x;
            y = 2 - iTemp_x + offset_y;
            if (x < 0 || x >= bord_x || y >= bord_y) {//超出边界
                result = false;
                break;
            }
            else if (y < 0) {
                continue;
            }
            else {//着色不能旋转
                rect = map.getrect(x, y);
                if (rect == null || rect.issetcolor) {
                    result = false;
                    break;
                }
            }
        }
    }
    return result;
};
//落下着色
tetrisgame.prototype.setmapcolor = function (tetris, map) {
    var iCount = tetris.rectarray.length;
    var x, y;
    for (var i = 0; i < iCount; i++) {
        x = tetris.rectarray[i].x;
        y = tetris.rectarray[i].y;
        map.aMapArray[x][y].issetcolor = true;
        map.aMapArray[x][y].color = tetris.color;
    }
};
tetrisgame.prototype.clearup = function (tetris, map) {
    var iCount = tetris.rectarray.length;
    var xCount = map.aMapArray.length;
    var yCount = 0;
    var bAll = false; //整行是否都着色了
    var bHas = false; //是否有着色的
    var cleararray = new Array();
    //获取俄罗斯方块中方块的最大y坐标
    for (var i = 0; i < iCount; i++) {
        if (yCount < tetris.rectarray[i].y) {
            yCount = tetris.rectarray[i].y;
        }
    }
    //计算哪些层需要消除
    for (var j = yCount; j >= 0; j--) {
        bAll = true;
        bHas = false;
        for (var i = 0; i < xCount; i++) {
            if (map.aMapArray[i][j].issetcolor) {
                bHas = true;
            }
            else {
                bAll = false;
            }
        }
        //整行都是，则记录起来
        if (bAll) {
            cleararray[cleararray.length] = j;
        }
        //整行都没有则break
        if (!bHas) {
            break;
        }
    }
    //消层;
    this.doclearup(cleararray);
    //降落
    this.falldown(cleararray);
}
//消层
tetrisgame.prototype.doclearup = function (cleararray) {
    var iCount = cleararray.length;
    var xCount = this.map.aMapArray.length;
    var score = 0;
    var yTemp;
    if (iCount > 0) {//根据记录中要消除的层数，将那一层填充为地图背景色
        for (var j = 0; j < iCount; j++) {
            yTemp = cleararray[j];
            for (var i = 0; i < xCount; i++) {
                this.map.aMapArray[i][yTemp].fillrect(this.map.backgroundcolor);
                this.map.aMapArray[i][yTemp].issetcolor = false;
            }
        }
        //消层后计算分数
        score = this.calcscore(cleararray);
        this.setscore(score);
    }
}
tetrisgame.prototype.falldown = function (cleararray) {
    var iCount = cleararray.length;
    var xCount = this.map.aMapArray.length;
    var yPre, yNow, color, bHasColor;

    if (iCount > 0) {
        for (var j = iCount - 1; j >= 0; j--) {//倒循环cleararray
            bHasColor = true;
            yNow = cleararray[j];
            while (yNow > 0 && bHasColor) {//自下向上 消除
                bHasColor = false;
                yPre = yNow - 1;
                for (var i = 0; i < xCount; i++) {
                    color = this.map.aMapArray[i][yPre].color; //获取上一层颜色
                    this.map.aMapArray[i][yNow].fillrect(color);
                    if (color != "#111") {
                        bHasColor = true;
                        this.map.aMapArray[i][yNow].issetcolor = true;
                    }
                    else {
                        this.map.aMapArray[i][yNow].issetcolor = false;
                    }
                }
                yNow = yNow - 1;
            }
        }
    }
};
//设置分数
tetrisgame.prototype.setscore = function (score) {
    var temp;
    this.score = this.score + score;
    if (this.level < 9) {
        temp = this.score / 20;
        this.level = temp.toFixed(0);
    }
    this.scorebord.innerHTML = "得分:" + this.score;
}
//计算得分 得分公式 2 * (n - 1) + 1 n 为连续消除了n层
tetrisgame.prototype.calcscore = function (cleararray) {
    var iCount = cleararray.length;
    var result, result1;
    //获取所有层数的和
    function sum(cleararray) {
        var sum = 0;
        for (var i = 0; i < iCount; i++) {
            sum = sum + cleararray[i];
        }
        return sum;
    }

    switch (iCount) {
        case 1 :
            return 1;//消除1层得1分
            break;
        case 2 :
            result = cleararray[0] - cleararray[1];
            if (result == 1) {//连续2层得3分
                return 3;
            }
            else {
                return 2;//不连续就得2分
            }
            break;
        case 3 :
            result = 3 * (cleararray[0] + cleararray[2]) / 2;
            result1 = sum(cleararray);
            if (result == result1) {
                return 7;//连续3层是7分
            }
            else {


                return 4;
            }
            break;
        case 4 :
            return 15;
            break;
        default :
            return 0;
    }
};
//定时器this对象丢失
tetrisgame.prototype.delay = function (obj, fn, time) {
    fnGameDelay = function () {
        fn.call(obj); // call方法会把fn方法中的this关键字替换成obj对象
    };
    return setTimeout('fnGameDelay()', time);
};
//暂停
tetrisgame.prototype.stop = function () {
    clearTimeout(this.timeOut);
};
//开始
tetrisgame.prototype.start = function () {
    var icolor, ikind, x, cleararray;
    if (this.tetris == null && this.tetris2 == null) {
        this.tetris = this.createrect();
        this.tetris.setbornxy(this.rectcreate_x, -1);
        this.tetris.born(this.map.ctx);
        this.tetris.show();
        this.tetris2 = this.createrect();
        this.tetris2.born(this.map2.ctx);
        this.tetris2.show();
        console.log("游戏开始");
    }
    if (this.tetris == null) {
        this.tetris = this.tetris2;
        this.tetris.setbornxy(this.rectcreate_x, -1);
        this.tetris.born(this.map.ctx);

        this.tetris2 = this.createrect();
        this.tetris2.born(this.map2.ctx);
        this.map2.refresh();
        this.tetris2.show();
    }
    if (this.iscanmove_down(this.tetris, this.map)) {
        this.tetris.move_down();

    }
    else {
        console.log("判断是否结束");
        //是否gameover
        console.log(this.isgameover(this.tetris))
        if (this.isgameover(this.tetris)) {
            this.gameover();
        }
        this.setmapcolor(this.tetris, this.map);
        //消层
        this.clearup(this.tetris, this.map);
        this.tetris = null;
    }


    console.log(level);
    //level=1111;
    this.timeOut = this.delay(this, this.start, level);


};
tetrisgame.prototype.keyboardEventsListeners = function (oEvent) {
    if (window.event) {// ie
        var direc = window.event.keyCode;
    } else if (oEvent.which) {// ff
        var direc = oEvent.which;
    }
    if (direc == 37 || direc == 65) {
        if (this.iscanmove_left(this.tetris, this.map)) {
            this.tetris.move_left();
        }

    }
    else if (direc == 39 || direc == 68) {
        if (this.iscanmove_right(this.tetris, this.map)) {
            this.tetris.move_right();
        }
    }
    else if (direc == 38 || direc == 87) {
        if (this.iscanturn(this.tetris, this.map)) {
            this.tetris.trun();
        }
    }
    else if (direc == 40 || direc == 83) {

//              if (this.iscanmove_down(this.tetris,this.map)){
//              this.tetris.move_down();
//              }

        this.stop();
        this.start();
    }
    else {
        return;
    }
};
var sel = document.getElementsByTagName("select").item(0);
var level;
var zt = true;
sel.onchange = function () {
    if (zt == false)return;
    if (sel.value == 1) {
        level = 800;
    } else if (sel.value == 2) {
        level = 450;
    }
    else if (sel.value == 3) {
        level = 120;
    }0
    //level =1000 - this.level * 100;
}

var canvas;
var ctx;
function init() {
    //var zt=true;
    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");

    canvas2 = document.getElementById("canvas2");
    ctx2 = canvas2.getContext("2d");
    var TetrisGame = new tetrisgame(canvas, canvas2);

    document.body.onkeydown = function (oEvent) {
        TetrisGame.keyboardEventsListeners.call(TetrisGame, oEvent);
    }
    document.getElementById("BtnStart").onclick = function () {
        if (sel.value == 0) {
            alert("请先选择游戏难度")
        }
        else {
            zt = false;
            TetrisGame.start.call(TetrisGame)
        }
        ;
    }
    document.getElementById("BtnStop").onclick = function () {
        TetrisGame.stop.call(TetrisGame);
    };
    document.getElementById("BtnReset").onclick = function () {
        TetrisGame.gameover.call(TetrisGame);
        zt = true;
        this.tetris = null;
        this.tetris2 = null;
        this.score = 0;
        //alert("Game Over!");
        this.map.refresh();
        this.map2.refresh();
    }
}


